/**
 * 用户服务模块
 *
 * 提供用户相关的业务逻辑处理，包括用户的增删改查操作。
 * 当前使用内存数组模拟数据库存储，在生产环境中应替换为真实的数据库操作。
 *
 * 采用单例模式确保整个应用中只有一个用户服务实例。
 *
 * @fileoverview 用户服务层实现
 */

import { randomUUID } from 'crypto';

import type { User, CreateUserRequest, UpdateUserRequest } from '@/types';
import { ApiError } from '@/types';
import { isValidEmail } from '@/utils/helpers';

/**
 * 用户服务类
 *
 * 管理用户相关的所有业务逻辑。
 * 提供用户的增删改查、搜索等功能。
 */
export class UserService {
  /**
   * 初始用户数据
   *
   * 用于模拟数据库中的初始数据，包含两个示例用户
   */
  private readonly initialUsers: User[] = [
    {
      id: '1',
      name: 'John Doe',
      email: 'john@example.com',
      createdAt: new Date('2024-01-01'),
      updatedAt: new Date('2024-01-01'),
    },
    {
      id: '2',
      name: 'Jane Smith',
      email: 'jane@example.com',
      createdAt: new Date('2024-01-02'),
      updatedAt: new Date('2024-01-02'),
    },
  ];

  /**
   * 运行时用户数据存储
   *
   * 使用数组模拟数据库表，在应用程序重启时会重置为初始数据。
   * 在生产环境中应替换为真实的数据库连接。
   */
  private users: User[];

  /**
   * 构造函数，初始化用户数据
   */
  public constructor() {
    this.users = [...this.initialUsers];
  }

  /**
   * 重置用户数据到初始状态
   *
   * 清空当前用户数据并恢复到初始状态，主要用于测试环境。
   * 在生产环境中不应使用此功能。
   *
   * @example
   * ```typescript
   * // 在测试前重置数据
   * const userService = new UserService();
   * userService.resetUsers();
   * console.log(await userService.getUsers()); // 返回初始的两个用户
   * ```
   */
  public resetUsers(): void {
    this.users.length = 0;
    this.users.push(...this.initialUsers);
  }

  /**
   * 获取用户列表（支持分页）
   *
   * 返回分页的用户数据。支持自定义页码和每页数据量。
   *
   * @param page - 页码，从1开始，默认为1
   * @param limit - 每页数据量，默认为10
   * @returns Promise<User[]> 用户数组
   *
   * @example
   * ```typescript
   * // 获取第一页，每页10条数据
   * const userService = new UserService();
   * const users = await userService.getUsers(1, 10);
   * console.log(users); // 用户数组
   *
   * // 获取第二页，每页5条数据
   * const users2 = await userService.getUsers(2, 5);
   * ```
   */
  public async getUsers(page: number = 1, limit: number = 10): Promise<User[]> {
    const startIndex = (page - 1) * limit;
    const endIndex = startIndex + limit;

    return this.users.slice(startIndex, endIndex);
  }

  /**
   * 根据用户ID获取单个用户
   *
   * 通过用户的唯一标识符查找并返回用户信息。
   * 如果用户不存在，抛出错误。
   *
   * @param id - 用户的唯一标识符
   * @returns Promise<User> 用户信息
   * @throws 如果用户不存在，抛出错误
   *
   * @example
   * ```typescript
   * const userService = new UserService();
   * try {
   *   const user = await userService.getUserById('1');
   *   console.log(user); // 用户信息
   * } catch (error) {
   *   console.log(error.message); // "用户未找到"
   * }
   * ```
   */ public async getUserById(id: string): Promise<User> {
    const user = this.users.find(u => u.id === id);

    if (!user) {
      throw new ApiError(404, '用户未找到');
    }

    return user;
  }

  /**
   * 创建新用户
   *
   * 根据提供的用户数据创建新用户。会自动验证邮箱格式和唯一性，
   * 生成唯一的用户ID，并设置创建和更新时间。
   *
   * @param userData - 创建用户所需的数据，包含姓名和邮箱
   * @returns Promise<User> 新创建的用户信息
   *
   * @throws 如果邮箱格式无效，抛出错误
   * @throws 如果邮箱已存在，抛出错误
   *
   * @example
   * ```typescript
   * const newUserData = {
   *   name: 'Alice Johnson',
   *   email: 'alice@example.com'
   * };
   *
   * const userService = new UserService();
   * try {
   *   const user = await userService.createUser(newUserData);
   *   console.log(user); // 新创建的用户信息
   * } catch (error) {
   *   console.log(error.message); // 错误信息
   * }
   * ```
   */ public async createUser(userData: CreateUserRequest): Promise<User> {
    // 验证邮箱格式
    if (!isValidEmail(userData.email)) {
      throw new ApiError(400, '邮箱格式无效');
    }

    // 检查邮箱是否已存在
    if (this.users.some(u => u.email === userData.email)) {
      throw new ApiError(409, '邮箱已存在');
    }

    // 创建新用户
    const newUser: User = {
      id: randomUUID(),
      name: userData.name,
      email: userData.email,
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    this.users.push(newUser);

    return newUser;
  }

  /**
   * 更新用户信息
   *
   * 根据用户ID更新用户的部分或全部信息。支持更新姓名和邮箱，
   * 所有字段都是可选的。如果更新邮箱，会验证格式和唯一性。
   *
   * @param id - 要更新的用户ID
   * @param userData - 要更新的用户数据，所有字段都是可选的
   * @returns Promise<User> 更新后的用户信息
   *
   * @throws 如果用户不存在，抛出错误
   * @throws 如果邮箱格式无效，抛出错误
   * @throws 如果邮箱已被其他用户使用，抛出错误
   *
   * @example
   * ```typescript
   * // 只更新姓名
   * const userService = new UserService();
   * try {
   *   const user1 = await userService.updateUser('1', { name: 'John Smith' });
   *   console.log(user1); // 更新后的用户信息
   * } catch (error) {
   *   console.log(error.message); // 错误信息
   * }
   * ```
   */ public async updateUser(
    id: string,
    userData: UpdateUserRequest
  ): Promise<User> {
    const userIndex = this.users.findIndex(u => u.id === id);

    if (userIndex === -1) {
      throw new ApiError(404, '用户未找到');
    }

    // 如果更新邮箱，验证格式和唯一性
    if (userData.email) {
      if (!isValidEmail(userData.email)) {
        throw new ApiError(400, '邮箱格式无效');
      }

      if (this.users.some(u => u.email === userData.email && u.id !== id)) {
        throw new ApiError(409, '邮箱已存在');
      }
    }

    // 更新用户数据
    const existingUser = this.users[Number(userIndex)];
    if (!existingUser) {
      throw new ApiError(404, '用户未找到');
    }

    const updatedUser: User = {
      id: existingUser.id,
      name: userData.name ?? existingUser.name,
      email: userData.email ?? existingUser.email,
      createdAt: existingUser.createdAt,
      updatedAt: new Date(),
    };

    this.users.splice(userIndex, 1, updatedUser);

    return updatedUser;
  }

  /**
   * 删除用户
   *
   * 根据用户ID删除指定用户。删除操作是不可逆的，
   * 请确保在调用前进行必要的确认。
   *
   * @param id - 要删除的用户ID
   * @returns Promise<void> 删除操作完成
   *
   * @throws 如果用户不存在，抛出错误
   *
   * @example
   * ```typescript
   * const userService = new UserService();
   * try {
   *   await userService.deleteUser('1');
   *   console.log('用户删除成功');
   * } catch (error) {
   *   console.log(error.message); // "用户未找到"
   * }
   * ```
   */ public async deleteUser(id: string): Promise<void> {
    const userIndex = this.users.findIndex(u => u.id === id);

    if (userIndex === -1) {
      throw new ApiError(404, '用户未找到');
    }

    this.users.splice(userIndex, 1);
  }

  /**
   * 搜索用户
   *
   * 根据查询关键词搜索用户，支持按姓名和邮箱进行模糊匹配。
   * 搜索不区分大小写，支持分页返回结果。
   *
   * @param query - 搜索关键词，会在用户姓名和邮箱中进行模糊匹配
   * @param page - 页码，从1开始，默认为1
   * @param limit - 每页数据量，默认为10
   * @returns Promise<User[]> 匹配的用户数组
   *
   * @example
   * ```typescript
   * // 搜索包含"john"的用户
   * const userService = new UserService();
   * const users1 = await userService.searchUsers('john');
   *
   * // 搜索包含"@example.com"的用户，获取第2页
   * const users2 = await userService.searchUsers('@example.com', 2, 5);
   *
   * console.log(users1); // 匹配的用户数组
   * ```
   */
  public async searchUsers(
    query: string,
    page: number = 1,
    limit: number = 10
  ): Promise<User[]> {
    const filteredUsers = this.users.filter(
      user =>
        user.name?.toLowerCase().includes(query.toLowerCase()) ||
        user.email?.toLowerCase().includes(query.toLowerCase())
    );

    const startIndex = (page - 1) * limit;
    const endIndex = startIndex + limit;

    return filteredUsers.slice(startIndex, endIndex);
  }
}

// 导出默认实例
export const userService = new UserService();
